package com.banksoft.admin.service.impl;

import com.banksoft.admin.SystemCache;
import com.banksoft.admin.bean.AmountType;
import com.banksoft.admin.bean.Status;
import com.banksoft.admin.dao.*;
import com.banksoft.admin.entity.*;
import com.banksoft.admin.service.TxApplyService;
import com.banksoft.common.ConfigHelper;
import com.banksoft.front.bean.Page;
import com.banksoft.front.util.RedPacketUtil;
import com.banksoft.util.DateUtil;
import com.banksoft.util.StringNumber;
import com.banksoft.util.StringUtil;
import com.banksoft.util.UUIDFactory;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by vanjoger on 2017/1/7.
 */
@Service
@Transactional
public class TxApplyServiceImpl implements TxApplyService {

    @Autowired
    BaseMyBatisDao baseMyBatisDao;
    @Autowired
    UserDao userDao;
    @Autowired
    UserMoneyDao userMoneyDao;
    @Autowired
    TxApplyDao txApplyDao;

    @Override
    public JSONObject verify(String id, String status, String bz, HttpServletRequest request) {
        TxApply dto = this.baseMyBatisDao.findById(TxApplyDao.class,id);
        if(dto==null)
            return StringUtil.FmtResult(false,"没有找到数据",null);
        if(!dto.getStatus().equals("0"))
            return StringUtil.FmtResult(false,"该申请已审核，无需再次审核",null);

        User user = baseMyBatisDao.findById(UserDao.class,dto.getUserId());
        if(user==null)
            return StringUtil.FmtResult(false,"用户不存在",null);

        List<UserMoney> moneys = userMoneyDao.findByUserId(user.getId());
        UserMoney money = null;
        if(StringUtil.isNotEmpty(moneys))
            money = moneys.get(0);
        if (Float.parseFloat(money.getFrozenAmount()) < Float.parseFloat(dto.getAmount()))
            return StringUtil.FmtResult(false, "账户余额不足！", null);

        Admin admin = (Admin) request.getSession().getAttribute(SystemCache.SESSION_ADMIN);
        dto.setStatus(status);
        dto.setShrName(admin.getLoginName());
        //dto.setShr("aaaa");
        dto.setShTime(new Date().getTime());
        dto.setBz(bz);
        this.baseMyBatisDao.update(TxApplyDao.class,dto);
        //增加资金流水
        AmountLog log = new AmountLog();
        log.setId(UUIDFactory.random());
        log.setCreateTime(new Date().getTime());
        log.setUserId(user.getId());
        log.setUserName(user.getNickName());


        if(status.equals("1")){//审核通过 则变动余额  新增资金流水
            String beforeFrozenAmount = money.getFrozenAmount();
            money.setFrozenAmount(StringNumber.sub(money.getFrozenAmount(),dto.getAmount()));
            this.baseMyBatisDao.update(UserMoneyDao.class,money);

            log.setCash("-"+dto.getAmount());
            log.setType(AmountType.TxFee.name());//扣除提现费用
            log.setBeforeCash(money.getCash());
            log.setBeforeBonus(money.getBonus());
            log.setBeforeFrozenAmount(beforeFrozenAmount);
            log.setAfterCash(money.getCash());
            log.setAfterBonus(money.getBonus());
            log.setAfterFrozenAmount(money.getFrozenAmount());
            this.baseMyBatisDao.insert(AmountLogDao.class,log);
            if(dto.getType().equals("1")) {//微信提现
                //发送红包  红包是单独行为 如果有一次发送失败 无法影响已有流程  在此不做逻辑处理
                Map map = sendSingleRedPacket(dto.getUserId(), Float.parseFloat(dto.getAmount()));
                if (!(Boolean) map.get("suc")) {
                    throw new NullPointerException(map.get("msg") + "");
                }
            }
        }else if(status.equals("2")){
            String beforeCash = money.getCash();
            String beforeFrozenAmount = money.getFrozenAmount();
            money.setFrozenAmount(StringNumber.sub(beforeFrozenAmount,dto.getAmount()));
            money.setCash(StringNumber.add(beforeCash,dto.getAmount()));
            this.baseMyBatisDao.update(UserMoneyDao.class,money);

            log.setCash(dto.getAmount());
            log.setType(AmountType.TxRejFee.name());//扣除提现费用
            log.setBeforeCash(beforeCash);
            log.setBeforeBonus(money.getBonus());
            log.setBeforeFrozenAmount(beforeFrozenAmount);
            log.setAfterCash(money.getCash());
            log.setAfterBonus(money.getBonus());
            log.setAfterFrozenAmount(money.getFrozenAmount());
            this.baseMyBatisDao.insert(AmountLogDao.class,log);
        }

        //保存系统日志
        if("1".equals(status)) {
            saveLog(request,"审核通过提现申请:"+JSONObject.fromObject(dto));
        }else if("2".equals(status)){
            saveLog(request,"审核拒绝提现申请:"+JSONObject.fromObject(dto));
        }
        return StringUtil.FmtResult(true,"操作成功",null);
    }



    /**
     * 发送单一红包
     * @param userId
     * @param amount
     */
    private Map sendSingleRedPacket(String userId, float amount)  {
        try {
            User user = this.baseMyBatisDao.findById(UserDao.class,userId);
            RedPacketRecord record = new RedPacketRecord();
            String id = getRecordId();

            record.setId(id);
            record.setAmount(amount + "");
            record.setOpenId(user.getOpenId());
            record.setSendDate(DateUtil.getCurrentDate());

            ConfigHelper instance = ConfigHelper.GetInstance();
            String accountName = instance.GetConfig("AccountName");
            String zfy = instance.GetConfig("Zfy");
            String activity = instance.GetConfig("ActivityName");
            String remark = instance.GetConfig("Remark");

            Map map = RedPacketUtil.sendRedPacket(record.getId(), accountName, user.getOpenId(), amount + "", zfy, StringUtil.getLocalIP(), activity, remark, SystemCache.getPaySetting());
            record.setIsSuc( map.get("suc")+"");
            this.baseMyBatisDao.insert(RedPacketRecordDao.class, record);
            return map;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    private String getRecordId() {
        String id = SystemCache.getPaySetting().getPayNo()+DateUtil.getFormatDate(new Date(),"yyyyMMdd")+ StringUtil.getRandom(10);
        RedPacketRecord record = this.baseMyBatisDao.findById(RedPacketRecordDao.class,id);
        if(record!=null)
            return getRecordId();
        return id;
    }

    @Override
    public JSONObject save(String userId, String amount, String remark, String type, String bankName, String cardName, String cardNo) {
        User user = baseMyBatisDao.findById(UserDao.class,userId);
        if(user==null)
            return StringUtil.FmtResult(false,"没有找到用户",null);
        if(!user.getStatus().equals(Status.NORMAL.name()))
            return StringUtil.FmtResult(false,"当前用户被冻结，无法提现",null);
        List<UserMoney> moneys = userMoneyDao.findByUserId(user.getId());
        UserMoney money = null;
        if(StringUtil.isNotEmpty(moneys))
            money = moneys.get(0);
        if(money==null)
            return StringUtil.FmtResult(false,"账户余额不足",null);
        if(Float.parseFloat(money.getCash())<Float.parseFloat(amount))
            return StringUtil.FmtResult(false,"账户余额不足",null);

        if("1".equals(type)) {
            Map params = new HashMap();
            params.put("userId",userId);
            String startDate = DateUtil.getFormatDate(new Date(),"yyyy-MM-dd")+" 00:00:00";
            String endDate = DateUtil.getFormatDate(new Date(),"yyyy-MM-dd")+" 23:59:59";
            params.put("startDate",DateUtil.getLongFormStrDate(startDate));
            params.put("endDate",DateUtil.getLongFormStrDate(endDate));
            int cnt = txApplyDao.countPage(params);
            if(cnt>5)
                return StringUtil.FmtResult(false,"您今日微信提现已满五次，请明天提现！",null);

            saveTxApply(user,amount,type,bankName,cardName,cardNo,money,"1");
            Map map = sendSingleRedPacket(userId, Float.parseFloat(amount));
            if ((Boolean) map.get("suc")) {//如果发送成功 将发送记录审核成功
               return StringUtil.FmtResult(true,"提现已通过，请接收红包！",null);
            }else{
                throw new NullPointerException((String) map.get("msg"));
            }
        }else{
            saveTxApply(user,amount,type,bankName,cardName,cardNo,money,"0");
        }



        return StringUtil.FmtResult(true,"提现已申请，待管理员审核",null);
    }

    /**
     * 保存提现记录
     * @param user
     * @param amount
     * @param type
     * @param bankName
     * @param cardName
     * @param cardNo
     * @param money
     */
    private void saveTxApply(User user,String amount,String type,String bankName,String cardName,String cardNo,UserMoney money,String status){
        TxApply apply = new TxApply();
        apply.setId(UUIDFactory.random());
        apply.setStatus(status);
        apply.setUserId(user.getId());
        apply.setCreateTime(new Date().getTime());
        apply.setAmount(amount);
        apply.setType(type);
        apply.setBankName(bankName);
        apply.setCardName(cardName);
        apply.setCardNo(cardNo);
        if(type.equals("1")){//微信提现
            apply.setDzAmount(amount+"");
            apply.setSxf("0");
        }else if(type.equals("2")){//银行卡提现
            String txFee = ConfigHelper.GetInstance().GetConfig("TxFee");
            String d = StringNumber.div(StringNumber.mul(amount,txFee),"1000");
            String dzAmount = StringNumber.sub(amount,d);
            apply.setDzAmount(dzAmount);
            apply.setSxf(d);
        }
        this.baseMyBatisDao.insert(TxApplyDao.class,apply);

        //冻结用户资金
        String beforeCash = money.getCash();
        String beforeFrozenAmount = money.getFrozenAmount();
        money.setCash(StringNumber.sub(beforeCash, amount));
        if(!"1".equals(status)){
            money.setFrozenAmount(StringNumber.add(beforeFrozenAmount, amount));
        }
        this.baseMyBatisDao.update(UserMoneyDao.class,money);
        //保存日志
        AmountLog log = new AmountLog();
        log.setId(UUIDFactory.random());
        log.setUserId(user.getId());
        log.setUserName(user.getNickName());
        log.setCreateTime(new Date().getTime());
        log.setBeforeCash(beforeCash);
        log.setBeforeBonus(money.getBonus());
        log.setCash("-"+amount);
        log.setBonus("0");
        log.setAfterCash(money.getCash());
        log.setAfterBonus(money.getBonus());
        log.setBeforeFrozenAmount(beforeFrozenAmount);
        log.setAfterFrozenAmount(money.getFrozenAmount());
        if(!"1".equals(status)){
            log.setType(AmountType.TxPreFee.name());
        }else{
            log.setType(AmountType.TxFee.name());
        }
        baseMyBatisDao.insert(AmountLogDao.class,log);
    }


    @Override
    public Page queryPage(Map map, int pageNo, int pageSize) {
        Page page = new Page(pageNo,pageSize);
        map.put("start",page.getStart());
        map.put("size",pageSize);

        List<AmountLog> list = this.txApplyDao.queryPage(map);
        Integer total = this.txApplyDao.countPage(map);
        page.setData(list);
        page.setTotal(total);
        return page;
    }

    @Override
    public JSONObject cancelTxApply(String id) {
        TxApply apply = this.baseMyBatisDao.findById(TxApplyDao.class,id);
        if(apply == null)
            return StringUtil.FmtResult(false,"没有找到该申请",null);
        if(!apply.getStatus().equals("0"))
            return StringUtil.FmtResult(false,"该申请无法取消",null);

        apply.setStatus("3");
        this.baseMyBatisDao.update(TxApplyDao.class,apply);

        List<UserMoney> moneys = userMoneyDao.findByUserId(apply.getUserId());
        UserMoney money = null;
        if(StringUtil.isNotEmpty(moneys))
            money = moneys.get(0);
        if(money!=null) {
            User user = this.baseMyBatisDao.findById(UserDao.class,apply.getUserId());

            String beforeCash = money.getCash();
            String beforeFrozenAmount = money.getFrozenAmount();
            money.setFrozenAmount(StringNumber.sub(beforeFrozenAmount, apply.getAmount()));
            money.setCash(StringNumber.add(beforeCash, apply.getAmount()));
            this.baseMyBatisDao.update(UserMoneyDao.class, money);

            AmountLog log = new AmountLog();
            log.setId(UUIDFactory.random());
            log.setCreateTime(new Date().getTime());
            log.setUserId(user.getId());
            log.setUserName(user.getNickName());
            log.setCash(apply.getAmount());
            log.setType(AmountType.TxCancelFee.name());//扣除提现费用
            log.setBeforeCash(beforeCash);
            log.setBeforeBonus(money.getBonus());
            log.setBeforeFrozenAmount(beforeFrozenAmount);
            log.setAfterCash(money.getCash());
            log.setAfterBonus(money.getBonus());
            log.setAfterFrozenAmount(money.getFrozenAmount());
            this.baseMyBatisDao.insert(AmountLogDao.class, log);
        }
        return StringUtil.FmtResult(true,"操作成功",null);
    }

    @Override
    public List<TxApply> list(Map map) {
        return this.txApplyDao.list(map);
    }

    @Override
    public List<TxApply> searchByPage1(Map map) {
        return this.txApplyDao.searchByPage1(map);
    }

    @Override
    public Integer count4Page1(Map map) {
        return this.txApplyDao.count4Page1(map);
    }

    /**
     * 保存系统日志
     * @param request
     * @param content
     */
    private void saveLog(HttpServletRequest request,String content){
        Admin admin = (Admin) request.getSession().getAttribute(SystemCache.SESSION_ADMIN);
        SystemLog systemLog = new SystemLog();
        systemLog.setId(UUIDFactory.random());
        systemLog.setOperateName(admin.getLoginName());
        systemLog.setOperateContent(content);
        systemLog.setIp(request.getRemoteHost());
        systemLog.setLogDate(new Date().getTime());
        this.baseMyBatisDao.insert(LogDao.class,systemLog);
    }
}
